package com.zlzlib.liblayoutmanager;

import android.content.Context;
import android.view.View;

/**
 * @Desc: 圆形滑动的类型
 * @Copyright:
 * @DateTime: 2021/8/17 15:45
 * @Author zlz
 * @Version 1.0
 */
public class LayoutCircleManager extends BaseLayoutManager {

    //圆心的位置 上下左右
    public static final int LEFT = 10;
    public static final int RIGHT = 11;
    public static final int TOP = 12;
    public static final int BOTTOM = 13;

    //item放置z轴 重叠的部分
    //左边在最上面
    public static final int LEFT_ON_TOP = 4;
    //右边在最上面
    public static final int RIGHT_ON_TOP = 5;
    //中间最上面
    public static final int CENTER_ON_TOP = 6;

    //滑动的圆形的半径大小
    private int radius;
    //每个item之间的相差角度
    protected int angleInterval;
    //旋转移除的角度
    private float maxRemoveAngle;
    private float minRemoveAngle;
    //圆心的位置 上下左右
    protected int gravity;
    //item交换翻转方向
    protected boolean flipRotate;
    //item放置z轴 重叠的部分
    private int zAlignment;

    public LayoutCircleManager(Context context) {
        this(context, INVALID_SIZE);
    }

    public LayoutCircleManager(Context context, int radius) {
        this(context, radius, BOTTOM);
    }

    public LayoutCircleManager(Context context, int radius, int gravity) {
        super(context, (gravity == LEFT || gravity == RIGHT) ? VERTICAL : HORIZONTAL, false);
        this.radius = radius;
        this.gravity = gravity;
        moveSpeed = 1 / 10f;
        angleInterval = 30;
        maxRemoveAngle = 90;
        minRemoveAngle = -90;
        flipRotate = false;
        zAlignment = LEFT_ON_TOP;
        setEnableBringCenterToFront(true);
    }

    @Override
    protected float setInterval() {
        return angleInterval;
    }

    @Override
    protected void setItemViewProperty(View itemView, float targetOffset) {
        switch (gravity) {
            case RIGHT:
            case TOP:
                if (flipRotate) {
                    itemView.setRotation(targetOffset);
                } else {
                    itemView.setRotation(360 - targetOffset);
                }
                break;
            case LEFT:
            case BOTTOM:
            default:
                if (flipRotate) {
                    itemView.setRotation(360 - targetOffset);
                } else {
                    itemView.setRotation(targetOffset);
                }
                break;
        }
    }

    @Override
    protected void setValueUp() {
        //设置半径
        radius = radius == INVALID_SIZE ? mDecoratedMeasurementInOther : radius;
    }

    @Override
    protected float maxRemoveOffset() {
        return maxRemoveAngle;
    }

    @Override
    protected float minRemoveOffset() {
        return minRemoveAngle;
    }

    @Override
    protected int calItemLeft(View itemView, float targetOffset) {
        switch (gravity) {
            case LEFT:
                return (int) (radius * Math.sin(Math.toRadians(90 - targetOffset)) - radius);
            case RIGHT:
                return (int) (radius - radius * Math.sin(Math.toRadians(90 - targetOffset)));
            case TOP:
            case BOTTOM:
            default:
                return (int) (radius * Math.cos(Math.toRadians(90 - targetOffset)));
        }
    }

    @Override
    protected int calItemTop(View itemView, float targetOffset) {
        switch (gravity) {
            case LEFT:
            case RIGHT:
                return (int) (radius * Math.cos(Math.toRadians(90 - targetOffset)));
            case TOP:
                return (int) (radius * Math.sin(Math.toRadians(90 - targetOffset)) - radius);
            case BOTTOM:
            default:
                return (int) (radius - radius * Math.sin(Math.toRadians(90 - targetOffset)));
        }
    }

    @Override
    protected float setViewElevation(View itemView, float targetOffset) {
        if (zAlignment == LEFT_ON_TOP)
            return (540 - targetOffset) / 72;
        else if (zAlignment == RIGHT_ON_TOP)
            return (targetOffset - 540) / 72;
        else
            return (360 - Math.abs(targetOffset)) / 72;
    }

    private static void assertGravity(int gravity) {
        if (gravity != LEFT && gravity != RIGHT && gravity != TOP && gravity != BOTTOM) {
            throw new IllegalArgumentException("必须是 LEFT RIGHT TOP 和 BOTTOM 之一");
        }
    }

    private static void assertZAlignmentState(int zAlignment) {
        if (zAlignment != LEFT_ON_TOP && zAlignment != RIGHT_ON_TOP && zAlignment != CENTER_ON_TOP) {
            throw new IllegalArgumentException("必须是 LEFT_ON_TOP RIGHT_ON_TOP 和 CENTER_ON_TOP 之一");
        }
    }

    public int getRadius() {
        return radius;
    }

    public void setRadius(int radius) {
        assertNotInLayoutOrScroll(null);
        if (this.radius == radius) return;
        this.radius = radius;
        removeAllViews();
    }

    public int getAngleInterval() {
        return angleInterval;
    }

    public void setAngleInterval(int angleInterval) {
        assertNotInLayoutOrScroll(null);
        if (this.angleInterval == angleInterval) return;
        this.angleInterval = angleInterval;
        removeAllViews();
    }

    public float getMaxRemoveAngle() {
        return maxRemoveAngle;
    }

    public void setMaxRemoveAngle(float maxRemoveAngle) {
        assertNotInLayoutOrScroll(null);
        if (this.maxRemoveAngle == maxRemoveAngle) return;
        this.maxRemoveAngle = maxRemoveAngle;
        requestLayout();
    }

    public float getMinRemoveAngle() {
        return minRemoveAngle;
    }

    public void setMinRemoveAngle(float minRemoveAngle) {
        assertNotInLayoutOrScroll(null);
        if (this.minRemoveAngle == minRemoveAngle) return;
        this.minRemoveAngle = minRemoveAngle;
        requestLayout();
    }

    public int getGravity() {
        return gravity;
    }

    public void setGravity(int gravity) {
        assertNotInLayoutOrScroll(null);
        assertGravity(gravity);
        if (this.gravity == gravity) return;
        this.gravity = gravity;
        if (gravity == LEFT || gravity == RIGHT) {
            setOrientation(VERTICAL);
        } else {
            setOrientation(HORIZONTAL);
        }
        requestLayout();
    }

    public boolean isFlipRotate() {
        return flipRotate;
    }

    public void setFlipRotate(boolean flipRotate) {
        assertNotInLayoutOrScroll(null);
        if (this.flipRotate == flipRotate) return;
        this.flipRotate = flipRotate;
        requestLayout();
    }

    public int getAlignment() {
        return zAlignment;
    }

    public void setAlignment(int zAlignment) {
        assertNotInLayoutOrScroll(null);
        assertZAlignmentState(zAlignment);
        if (this.zAlignment == zAlignment) return;
        this.zAlignment = zAlignment;
        requestLayout();
    }
}
